using System;
using System.Xml;
using System.Xml.Linq;

namespace EstimationStudio.Core
{
	/// <summary>
	///  The EstimateReader class provides the facility to open an estimate.
	/// </summary>
	public class EstimateReader
	{
		private void LoadEstimate (XmlDocument xmlDocument, Estimate estimate)
		{
			XmlElement xmlEstimate = xmlDocument.DocumentElement;
			estimate.EstimateId = xmlEstimate.GetAttribute("EstimateId");
			estimate.DateEstimated = DateTime.Parse(xmlEstimate.GetAttribute("DateEstimated"));
			estimate.Title = xmlEstimate.GetAttribute("Name");
			estimate.ProblemDescription = xmlEstimate.GetAttribute("Description");
			estimate.SolutionNotes = xmlEstimate.GetAttribute("SolutionNotes");

			LoadProjectPhase(xmlEstimate, estimate);
			LoadAdjustmentFactors(xmlEstimate, estimate);
			LoadFeatures(xmlEstimate, estimate);
		}

		private void LoadProjectPhase (XmlElement xmlEstimate, Estimate estimate)
		{
			XmlNode xmlProjectPhase = xmlEstimate.GetElementsByTagName("ProjectPhase")[0];
			estimate.ProjectPhase.Name = xmlProjectPhase.Attributes["Name"].Value;

			ErrorVariability errorVariability = new ErrorVariability();
			errorVariability.Low = Double.Parse(xmlProjectPhase.Attributes["ErrorVariability.Low"].Value);
			errorVariability.High = Double.Parse(xmlProjectPhase.Attributes["ErrorVariability.High"].Value);

			estimate.ProjectPhase.ErrorVariability = errorVariability;
		}

		private void LoadAdjustmentFactors (XmlElement xmlEstimate, Estimate estimate)
		{
			XmlNodeList xmlAdjustmentFactors = xmlEstimate.GetElementsByTagName("AdjustmentFactor");
			foreach (XmlNode xmlAdjustmentFactor in xmlAdjustmentFactors)
			{
				String name = xmlAdjustmentFactor.Attributes["Name"].Value;
				String description = xmlAdjustmentFactor.Attributes["Description"].Value;
				Double veryLow = Double.Parse(xmlAdjustmentFactor.Attributes["Rating.VeryLow"].Value);
				Double low = Double.Parse(xmlAdjustmentFactor.Attributes["Rating.Low"].Value);
				Double high = Double.Parse(xmlAdjustmentFactor.Attributes["Rating.High"].Value);
				Double veryHigh = Double.Parse(xmlAdjustmentFactor.Attributes["Rating.VeryHigh"].Value);
				Double extraHigh = Double.Parse(xmlAdjustmentFactor.Attributes["Rating.ExtraHigh"].Value);
								
				AdjustmentVariability adjustmentVariability = new AdjustmentVariability(veryLow, low, high, veryHigh, extraHigh);
				AdjustmentFactor adjustmentFactor = new AdjustmentFactor
                {
                    Name = name,
                    Description = description,
                    AdjustmentVariability = adjustmentVariability
                };
				adjustmentFactor.CurrentRating = (Rating) Enum.Parse(typeof(Rating), xmlAdjustmentFactor.Attributes["CurrentRating"].Value);

				estimate.AdjustmentFactors.Add(adjustmentFactor);
			}
		}

		private void LoadFeatures (XmlElement xmlEstimate, Estimate estimate)
		{
			XmlNodeList xmlFeatures = xmlEstimate.GetElementsByTagName("Feature");
			foreach (XmlNode xmlFeature in xmlFeatures)
			{
				Feature feature = new Feature();
				feature.Name = xmlFeature.Attributes["Name"].Value;
				feature.Description = xmlFeature.Attributes["Description"].Value;
				feature.SolutionNotes = xmlFeature.Attributes["SolutionNotes"].Value;
				feature.BestCase = Double.Parse(xmlFeature.Attributes["BestCase"].Value);
				feature.NominalCase = Double.Parse(xmlFeature.Attributes["MostLikelyCase"].Value);
				feature.WorstCase = Double.Parse(xmlFeature.Attributes["WorstCase"].Value);

				estimate.Features.Add(feature);
			}
		}

		/// <summary>
		///  Opens an estimate at the specified path.
		/// </summary>
		/// <param name="path">The path to the estimate to open.</param>
		/// <returns>The estimate that was opened from the specified path.</returns>
		public Estimate Open (String path)
		{
			XmlDocument xmlDocument = new XmlDocument();
			xmlDocument.Load(path);

			Estimate estimate = new Estimate();
			LoadEstimate(xmlDocument, estimate);

			return estimate;
		}

		/// <summary>
		/// Opens the specified x element.
		/// </summary>
		/// <param name="xElement">The x element.</param>
		/// <returns></returns>
		public Estimate Open (XElement xElement)
		{
			XmlDocument xmlDocument = new XmlDocument();
			xmlDocument.LoadXml(xElement.ToString());

			Estimate estimate = new Estimate();
			LoadEstimate(xmlDocument, estimate);

			return estimate;
		}
	}
}